import { _decorator, CCClass, game, Rect, UITransform,Node, Label, Button } from "cc";
import { CardData } from "../Data/CardData";
import { ObjectPool } from "../utils/ObjectPool/ObjectPool";
import { UIBase } from "../utils/UIFramework/UIBase";
import { CardUI } from "../Entity/cardUI";
import EntityManager from "../utils/EntitySystem/EntityManager";
import BattleStateBlock from "../StateBlock/BattleStateBlock";
import CardStateBlock from "../StateBlock/CardStateBlock";
import DataManager from "../utils/DataSystem/DataManager";
import { BattleData } from "../Data/BattleData";
import { ProbeEventList } from "../utils/EventSystem/EventList";
const { ccclass, property } = _decorator;


export interface ICardDragData{
    /**
     * 拖动落点是否在手牌外
     */
    isOutOfHand : boolean,
    /**
     * 拖动落点的卡牌。如果没有卡牌则为null
     */
    targetCard : CardStateBlock,
    battle : BattleStateBlock,
    gameUI : GameUI
}

/**
 * Game 的UI
 */
@ccclass('gameUI')
export class GameUI extends UIBase{

    /**
     * CardUI对象池,实现其复用
     */
    private cardUIPool : ObjectPool<CardUI> = new ObjectPool(this.loadCardUI);

    /**
     * 战斗状态机
     */
    public Battle : BattleStateBlock = new BattleStateBlock();

    public ReturnMenu : ProbeEventList = new ProbeEventList()

    public get hand() : Node {
        return this.uiMap.GetNode("hand")
    }
    
    public get ally() : Node
    {
        return this.uiMap.GetNode("ally")
    }

    
    public get enemy() : Node {
        return this.uiMap.GetNode("enemy");
    }

    
    public get taskText() : Node {
        return this.uiMap.GetNode("taskText");
    }
    
    

    public async onOpen(): Promise<void> {
        this.uiMap.GetNode("turnEndButton").on(Button.EventType.CLICK,this._onTurnEndButtonDown,this);
        this.Battle.cost.ValueChanged.AddFunc(
            this._changCost
            ,this
        );
        this.Battle.limitCost.ValueChanged.AddFunc(
            this._changCost
            ,this
        );
        this.Battle.handZone.ValueChanged.AddFunc(
            this._updateHand,
            this
        );
        this.Battle.allyZone.ValueChanged.AddFunc(
            this._updateAlly,
            this
        );
        this.Battle.enemyZone.ValueChanged.AddFunc(
            this._updateEnemy,
            this
        );

        this.Battle.WinEvent.AddFunc(
            this._onWin,
            this
        )

        this.uiMap.GetNode("win").active = false;
        this.uiMap.GetNode("winReturnButton").on(Button.EventType.CLICK,this._returnMenu,this);
    }

    private _returnMenu() {
        this.ReturnMenu.DoEvent();
    }

    public onClose(): void {
        this.uiMap.GetNode("turnEndButton").off(Button.EventType.CLICK,this._onTurnEndButtonDown,this);
        this.Battle.cost.ValueChanged.RemoveFunc(
            this._changCost
            ,this
        );
        this.Battle.limitCost.ValueChanged.RemoveFunc(
            this._changCost
            ,this
        );
        this.Battle.handZone.ValueChanged.RemoveFunc(
            this._updateHand,
            this
        );
        this.Battle.enemyZone.ValueChanged.RemoveFunc(
            this._updateEnemy,
            this
        )
        this.Battle.Close();

        this.ReturnMenu.Clear();
    }

    public BattleStart(data : BattleData)
    {
        this.Battle.initBattleData = data;
        this.Battle.Start();
        this.taskText.getComponent(Label).string = data.taskText;
    }

    /**
     * 更新手牌区
     */
    private async _updateHand(self : GameUI,valueArray : Array<CardStateBlock>[]){
        let value = valueArray[0];
        for (const cardUI of self.hand.getComponentsInChildren(CardUI)) {
            cardUI.CloseSelf();
        }
        for(const card of value){
            await self.AddHand(card);
        }
    }

    /**
     * 更新友方随从区
     */
    private async _updateAlly(self : GameUI,valueArray : Array<CardStateBlock>[]){
        let value = valueArray[0];
        for (const cardUI of self.ally.getComponentsInChildren(CardUI)) {
            cardUI.CloseSelf();
        }
        for(const card of value){
            await self.AddAlly(card);
        }
    }

    /**
     * 更新敌人区
     */
    private async _updateEnemy(self : GameUI,valueArray : Array<CardStateBlock>[]){
        let value = valueArray[0];
        for (const cardUI of self.enemy.getComponentsInChildren(CardUI)) {
            cardUI.CloseSelf();
        }
        for(const card of value){
            await self.AddEnemy(card);
        }
    }


    /**
     * 当卡牌移动结束后调用
     * @param self 
     * @param data 
     */
    private async onCardMoveEnd(self : GameUI,dataArray : CardUI[]) {
        let data = dataArray[0];
        let dragData : ICardDragData = { isOutOfHand : true, targetCard : null, battle:self.Battle,gameUI:self }; 
        /**
         * 卡牌的Rect
         */
        let selfCardRect = data.UITransform.getBoundingBoxToWorld();
        /**
         * 手牌区域的Rect
         */
        let handRect = self.uiMap.GetComponent<UITransform>("handZone",UITransform.name).getBoundingBoxToWorld();     
        if(selfCardRect.intersects(handRect)){
            dragData.isOutOfHand = false;
            dragData.targetCard = null;
            // data.returnPos();
        }else{
            let allCardUIs = self.node.getComponentsInChildren(CardUI);
            for (const card of allCardUIs) {
                let rect = card.getComponent(UITransform).getBoundingBoxToWorld();
                if(rect.contains(data.touchEvent.getUILocation()) && card != data)
                {
                    dragData.targetCard = card.getComponent(CardUI).Card;
                }
            }
        }
        data.dragInfo = dragData;
    }

    /**
     * CardUI的工厂函数
     * @returns 
     */
    private async loadCardUI(){
        var card = await EntityManager.Instance.GetEntity<CardUI>("card");
        return card
    }

    private _changCost(self : GameUI){
        let label = self.uiMap.GetComponent<Label>("manaCostText",Label.name);
        label.string = self.Battle.cost.Value.toString() + "/" + self.Battle.limitCost.Value.toString()
    }

    private _onTurnEndButtonDown(){
        this.Battle.EndTurn();
    }

    private _onWin(self : GameUI)
    {
        self.uiMap.GetNode("win").active = true;
    }

    public async AddHand(card : CardStateBlock){
        let cardUI = await this.cardUIPool.LentItem(card,this.hand);
        cardUI.CardDragEnd.AddFunc(this.onCardMoveEnd,this);
        cardUI.toHand();
    }

    public async AddAlly(card : CardStateBlock){
        let cardUI = await this.cardUIPool.LentItem(card,this.ally);
        cardUI.CardDragEnd.AddFunc(this.onCardMoveEnd,this);
        cardUI.toAlly();
    }

    public async AddEnemy(card : CardStateBlock){
        let cardUI = await this.cardUIPool.LentItem(card,this.enemy);
        cardUI.CardDragEnd.AddFunc(this.onCardMoveEnd,this);
        cardUI.toEnemy();
    }

    public RemoveHand(cardUI : CardUI){
        cardUI.CloseSelf();
    }
} 